package com.gitee.l0km.codegen.base.generator;

import static com.gitee.l0km.codegen.base.generator.GeneratorUtils.NEW_LINE;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitee.l0km.com4j.base.Assert;

public class CodeWriter {
	private static final Logger logger = LoggerFactory.getLogger(CodeWriter.class);

	private String folder = ".";
	private String sourceFile="sourceFile";
	private File outputFolder;
	private boolean saveCurrentFile = true;
	public CodeWriter(File outputFolder) {
		Assert.notNull(outputFolder, "outputFolder");
		this.outputFolder = outputFolder;
	}

	public void setCurrentSourceFilename(String folder, String sourceFile) {
		Assert.notEmpty(folder, "folder");
		Assert.notEmpty(sourceFile, "sourceFile");
		this.folder = folder;
		this.sourceFile = sourceFile;
	}

	public final void write(String content) throws IOException {
		write(FileBuilder.from(outputFolder).append(folder).append(sourceFile).build(), content);
	}

	// -- Write the parsed template to the file -----------------------------------

	public final void write(String path, String content) throws IOException {
		write(FileBuilder.from(outputFolder).append(path).build(), content);
	}

	public final void write(File file, String content) throws IOException {
		if(!this.saveCurrentFile){
			logger.info("SKIP : {}",file.getAbsolutePath());
			return;
		}
		logger.info("WRITING: {}",file.getAbsolutePath());
		// -- create all the directories
		File folder = new File(file.getParent());
		if (!folder.exists()) {
			// -- check if the creation of the directories worked
			if (!folder.mkdirs())
				throw new IOException(String.format("Unable to create the directory to write the file to. :\n%s",
						file.getCanonicalPath()));
		}
		byte[] b = content.getBytes();
		//去掉bom头重新生成字符串,否则java编译器报错
		if(b[0]==(byte)0xef&&b[1]==(byte)0xbb&&b[2]==(byte)0xbf)
			content = new String(b,3,b.length-3,"UTF-8"); 
		// 替换为当前系统的换行符
		content = Pattern.compile("(\r\n|\n|\r)", Pattern.MULTILINE).matcher(content).replaceAll(NEW_LINE);

		Writer writer=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));//指定UTF-8编码
		try {
			// -- write our content to the file
			if(file.getName().matches(".*\\.(c(pp|\\+\\+|c|xx)?|h(pp)?)$"))
			{
				/* 
				 * 有一些C/C++编译器要求代码以新行结束，否则会有编译警告，为消除编译警告
				 * 只删除前部空格,保留尾部空格 
				 */
				writer.write(leftTrim(content));//去除前部空格
				
			}else{
				writer.write(content.trim());//去除前后空格
			}
			writer.flush();
		} finally {
			writer.close();
		}
	}

    /**
     * 与{@link String#trim()}类似,删除字符串前部的空格
     * @param input
     */
    public static String leftTrim(String input) {
    	if(null == input){
    		return null;
    	}
        int len = input.length();
        int st = 0;

        while ((st < len) && (input.charAt(st) <= ' ')) {
            st++;
        }
        return (st > 0) ? input.substring(st, len) : input;
    }
	/**
	 * @param outputFolder
	 *            要设置的 outputFolder
	 */
	public final void setOutputFolder(File outputFolder) {
		this.outputFolder = outputFolder;
	}

	/**
	 * velocity 脚本调用，指定是否保存当前生成的文件
	 * @param saveCurrentFile
	 */
	public void setSaveCurrentFile(boolean saveCurrentFile) {
		this.saveCurrentFile = saveCurrentFile;
	}

	public boolean isSaveCurrentFile() {
		return saveCurrentFile;
	}
}
